package cn.rwklyd.BookKeeping.service.impl;

import cn.rwklyd.BookKeeping.constant.MessageConstant;
import cn.rwklyd.BookKeeping.mapper.mybatisPlus.BudgetCategoryMapper;
import cn.rwklyd.BookKeeping.mapper.mybatisPlus.BudgetMapper;
import cn.rwklyd.BookKeeping.mapper.mybatisPlus.CategoryMapper;
import cn.rwklyd.BookKeeping.mapper.mybatisPlus.TransactionMapper;
import cn.rwklyd.BookKeeping.pojo.Budget;
import cn.rwklyd.BookKeeping.pojo.BudgetCategory;
import cn.rwklyd.BookKeeping.pojo.Category;
import cn.rwklyd.BookKeeping.pojo.Result;
import cn.rwklyd.BookKeeping.pojo.Transaction;
import cn.rwklyd.BookKeeping.pojo.vo.BudgetCategoryVO;
import cn.rwklyd.BookKeeping.service.BudgetCategoryService;
import cn.rwklyd.BookKeeping.util.UserUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.List;

@Service
@Slf4j
public class BudgetCategoryServiceImpl extends ServiceImpl<BudgetCategoryMapper, BudgetCategory> implements BudgetCategoryService {

    @Autowired
    private BudgetMapper budgetMapper;
    
    @Autowired
    private CategoryMapper categoryMapper;

    @Autowired
    private TransactionMapper transactionMapper;

    @Override
    @Transactional
    public Result<String> addBudgetCategory(BudgetCategory budgetCategory) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }

        // 参数验证
        if (budgetCategory.getBudgetId() == null) {
            return Result.error("预算ID不能为空");
        }
        
        if (budgetCategory.getCategoryId() == null) {
            return Result.error("分类ID不能为空");
        }
        
        if (budgetCategory.getAmount() == null) {
            return Result.error("分类预算金额不能为空");
        }
        
        if (budgetCategory.getAmount().doubleValue() <= 0) {
            return Result.error("分类预算金额必须大于0");
        }

        // 验证预算是否存在且属于当前用户
        Budget budget = budgetMapper.selectById(budgetCategory.getBudgetId());
        if (budget == null || budget.getStatus() == 0) {
            return Result.error("预算不存在");
        }
        
        if (!budget.getUserId().equals(userId)) {
            return Result.error("无权操作此预算");
        }

        // 验证分类是否存在
        Category category = categoryMapper.selectById(budgetCategory.getCategoryId());
        if (category == null || category.getIsDeleted() == 1) {
            return Result.error("分类不存在");
        }

        // 检查是否已存在相同的预算分类组合
        LambdaQueryWrapper<BudgetCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BudgetCategory::getBudgetId, budgetCategory.getBudgetId())
                   .eq(BudgetCategory::getCategoryId, budgetCategory.getCategoryId())
                   .eq(BudgetCategory::getStatus, 1);
        
        long count = this.count(queryWrapper);
        if (count > 0) {
            return Result.error("该预算下已存在此分类的预算设置");
        }
        
        // 计算当前预算下所有分类预算金额之和
        LambdaQueryWrapper<BudgetCategory> sumWrapper = new LambdaQueryWrapper<>();
        sumWrapper.eq(BudgetCategory::getBudgetId, budgetCategory.getBudgetId())
                 .eq(BudgetCategory::getStatus, 1);
        
        List<BudgetCategory> existingCategories = this.list(sumWrapper);
        BigDecimal currentSum = existingCategories.stream()
                .map(BudgetCategory::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        // 检查添加新分类预算后是否超过总预算
        BigDecimal newTotal = currentSum.add(budgetCategory.getAmount());
        if (newTotal.compareTo(budget.getAmount()) > 0) {
            return Result.error("分类预算总和不能超过总预算金额");
        }
        
        // 设置默认值
        budgetCategory.setCreateTime(LocalDateTime.now());
        budgetCategory.setUpdateTime(LocalDateTime.now());
        budgetCategory.setStatus(1); // 默认启用
        
        // 保存预算分类
        boolean success = this.save(budgetCategory);
        if (success) {
            return Result.success("添加预算分类成功");
        } else {
            return Result.error("添加预算分类失败");
        }
    }

    @Override
    @Transactional
    public Result<String> deleteBudgetCategory(Long id) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }
        
        // 查询预算分类是否存在
        BudgetCategory budgetCategory = this.getById(id);
        if (budgetCategory == null) {
            return Result.error("预算分类不存在");
        }
        
        // 验证预算是否属于当前用户
        Budget budget = budgetMapper.selectById(budgetCategory.getBudgetId());
        if (budget == null || !budget.getUserId().equals(userId)) {
            return Result.error("无权操作此预算分类");
        }
        
        // 逻辑删除（将status设为0）
        budgetCategory.setStatus(0);
        budgetCategory.setUpdateTime(LocalDateTime.now());
        
        boolean success = this.updateById(budgetCategory);
        if (success) {
            return Result.success("删除预算分类成功");
        } else {
            return Result.error("删除预算分类失败");
        }
    }

    @Override
    @Transactional
    public Result<String> updateBudgetCategory(BudgetCategory budgetCategory) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }
        
        if (budgetCategory.getId() == null) {
            return Result.error("预算分类ID不能为空");
        }
        
        if (budgetCategory.getAmount() != null && budgetCategory.getAmount().doubleValue() <= 0) {
            return Result.error("分类预算金额必须大于0");
        }
        
        // 查询原记录
        BudgetCategory existingCategory = this.getById(budgetCategory.getId());
        if (existingCategory == null || existingCategory.getStatus() == 0) {
            return Result.error("预算分类不存在");
        }
        
        // 验证预算是否属于当前用户
        Budget budget = budgetMapper.selectById(existingCategory.getBudgetId());
        if (budget == null || budget.getStatus() == 0 || !budget.getUserId().equals(userId)) {
            return Result.error("无权操作此预算分类");
        }
        
        // 如果要修改金额，需要验证总和不超过预算
        if (budgetCategory.getAmount() != null && !budgetCategory.getAmount().equals(existingCategory.getAmount())) {
            // 计算当前预算下所有分类预算金额之和（不包括当前修改的分类）
            LambdaQueryWrapper<BudgetCategory> sumWrapper = new LambdaQueryWrapper<>();
            sumWrapper.eq(BudgetCategory::getBudgetId, existingCategory.getBudgetId())
                     .eq(BudgetCategory::getStatus, 1)
                     .ne(BudgetCategory::getId, existingCategory.getId());
            
            List<BudgetCategory> otherCategories = this.list(sumWrapper);
            BigDecimal otherSum = otherCategories.stream()
                    .map(BudgetCategory::getAmount)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            
            // 检查修改后是否超过总预算
            BigDecimal newTotal = otherSum.add(budgetCategory.getAmount());
            if (newTotal.compareTo(budget.getAmount()) > 0) {
                return Result.error("分类预算总和不能超过总预算金额");
            }
        }
        
        // 保留原始的budgetId和categoryId
        budgetCategory.setBudgetId(existingCategory.getBudgetId());
        budgetCategory.setCategoryId(existingCategory.getCategoryId());
        
        // 设置更新时间
        budgetCategory.setUpdateTime(LocalDateTime.now());
        
        boolean success = this.updateById(budgetCategory);
        if (success) {
            return Result.success("更新预算分类成功");
        } else {
            return Result.error("更新预算分类失败");
        }
    }

    @Override
    public Result<BudgetCategory> getBudgetCategoryById(Long id) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }
        
        // 查询预算分类
        BudgetCategory budgetCategory = this.getById(id);
        if (budgetCategory == null || budgetCategory.getStatus() == 0) {
            return Result.error("预算分类不存在");
        }
        
        // 验证预算是否属于当前用户
        Budget budget = budgetMapper.selectById(budgetCategory.getBudgetId());
        if (budget == null || budget.getStatus() == 0 || !budget.getUserId().equals(userId)) {
            return Result.error("无权查看此预算分类");
        }
        
        return Result.success(budgetCategory);
    }

    @Override
    public Result<IPage<BudgetCategory>> listBudgetCategories(Long budgetId, Integer page, Integer pageSize) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }
        
        if (budgetId == null) {
            return Result.error("预算ID不能为空");
        }
        
        // 验证预算是否属于当前用户
        Budget budget = budgetMapper.selectById(budgetId);
        if (budget == null || budget.getStatus() == 0) {
            return Result.error("预算不存在");
        }
        
        if (!budget.getUserId().equals(userId)) {
            return Result.error("无权查看此预算的分类预算");
        }
        
        // 构建查询条件
        LambdaQueryWrapper<BudgetCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BudgetCategory::getBudgetId, budgetId)
                   .eq(BudgetCategory::getStatus, 1)
                   .orderByDesc(BudgetCategory::getCreateTime);
        
        // 设置默认值
        if (page == null) page = 1;
        if (pageSize == null) pageSize = 10;
        
        // 分页查询
        Page<BudgetCategory> pageParam = new Page<>(page, pageSize);
        IPage<BudgetCategory> budgetCategoryPage = this.page(pageParam, queryWrapper);
        
        return Result.success(budgetCategoryPage);
    }

    @Override
    public Result<IPage<BudgetCategoryVO>> listBudgetCategoriesWithExpense(Long budgetId, Integer page, Integer pageSize) {
        // 获取当前用户ID
        Long userId = UserUtils.getCurrentUserId();
        if (userId == null) {
            return Result.error(MessageConstant.USER_NOT_LOGIN);
        }
        
        if (budgetId == null) {
            return Result.error("预算ID不能为空");
        }
        
        // 验证预算是否属于当前用户
        Budget budget = budgetMapper.selectById(budgetId);
        if (budget == null || budget.getStatus() == 0) {
            return Result.error("预算不存在");
        }
        
        if (!budget.getUserId().equals(userId)) {
            return Result.error("无权查看此预算的分类预算");
        }
        
        // 构建查询条件
        LambdaQueryWrapper<BudgetCategory> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(BudgetCategory::getBudgetId, budgetId)
               .eq(BudgetCategory::getStatus, 1)
               .orderByDesc(BudgetCategory::getCreateTime);
        
        // 设置默认值
        if (page == null) page = 1;
        if (pageSize == null) pageSize = 10;
        
        // 分页查询
        Page<BudgetCategory> pageParam = new Page<>(page, pageSize);
        IPage<BudgetCategory> budgetCategoryPage = this.page(pageParam, queryWrapper);
        
        // 计算当月总支出
        final BigDecimal totalMonthlyExpense = getMonthlyTotalExpense(userId, budget.getCreateTime());
        
        // 计算剩余预算
        final BigDecimal remainingBudget;
        if (budget.getAmount().compareTo(totalMonthlyExpense) > 0) {
            remainingBudget = budget.getAmount().subtract(totalMonthlyExpense);
        } else {
            remainingBudget = BigDecimal.ZERO;
        }
        
        // 保存总预算金额为final变量
        final BigDecimal totalBudget = budget.getAmount();
        
        // 创建返回结果
        BudgetCategoryVO result = new BudgetCategoryVO();
        result.setTotalMonthlyExpense(totalMonthlyExpense);
        result.setTotalBudget(totalBudget);
        result.setRemainingBudget(remainingBudget);
        
        // 处理分类列表
        List<BudgetCategoryVO.CategoryDetail> categoryDetails = budgetCategoryPage.getRecords().stream()
            .map(budgetCategory -> {
                BudgetCategoryVO.CategoryDetail detail = new BudgetCategoryVO.CategoryDetail();
                detail.setBudgetCategory(budgetCategory);
                
                // 获取分类信息
                Category category = categoryMapper.selectById(budgetCategory.getCategoryId());
                detail.setCategory(category);
                
                // 获取本月该分类的消费总额
                BigDecimal monthlyExpense = getMonthlyExpenseByCategoryId(userId, budgetCategory.getCategoryId(), 
                                                                 budget.getCreateTime());
                detail.setMonthlyExpense(monthlyExpense);
                
                // 计算预算使用百分比
                if (budgetCategory.getAmount().compareTo(BigDecimal.ZERO) > 0) {
                    BigDecimal percentage = monthlyExpense.multiply(new BigDecimal("100"))
                                   .divide(budgetCategory.getAmount(), 2, BigDecimal.ROUND_HALF_UP);
                    detail.setUsagePercentage(percentage);
                } else {
                    detail.setUsagePercentage(BigDecimal.ZERO);
                }
                
                return detail;
            })
            .collect(java.util.stream.Collectors.toList());
        
        result.setCategories(categoryDetails);
        
        // 创建包含分页信息的返回对象
        Page<BudgetCategoryVO> voPage = new Page<>(budgetCategoryPage.getCurrent(), budgetCategoryPage.getSize(), 
                                               budgetCategoryPage.getTotal());
        voPage.setRecords(java.util.Collections.singletonList(result));
        
        return Result.success(voPage);
    }

    /**
     * 获取指定用户、指定分类、指定月份的消费总额
     * @param userId 用户ID
     * @param categoryId 分类ID
     * @param dateInMonth 月份中的任意一天
     * @return 消费总额
     */
    private BigDecimal getMonthlyExpenseByCategoryId(Long userId, Long categoryId, LocalDateTime dateInMonth) {
        // 获取当前月的第一天和最后一天
        YearMonth yearMonth = YearMonth.from(dateInMonth);
        LocalDateTime firstDay = yearMonth.atDay(1).atStartOfDay();
        LocalDateTime lastDay = yearMonth.atEndOfMonth().atTime(23, 59, 59);
        
        // 查询该月该分类的所有交易记录（只计算支出）
        LambdaQueryWrapper<Transaction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Transaction::getUserId, userId)
                   .eq(Transaction::getCategoryId, categoryId)
                   .eq(Transaction::getIsDeleted, 0)
                   .ge(Transaction::getTransactionDate, firstDay)
                   .le(Transaction::getTransactionDate, lastDay)
                   .exists("SELECT 1 FROM category c WHERE c.id = transaction.category_id AND c.spend = 1");
        
        // 查询交易记录
        List<Transaction> transactions = transactionMapper.selectList(queryWrapper);
        
        // 计算总额
        BigDecimal total = transactions.stream()
                .map(Transaction::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        return total;
    }

    /**
     * 获取指定用户、指定月份的所有支出总额
     * @param userId 用户ID
     * @param dateInMonth 月份中的任意一天
     * @return 支出总额
     */
    private BigDecimal getMonthlyTotalExpense(Long userId, LocalDateTime dateInMonth) {
        // 获取当前月的第一天和最后一天
        YearMonth yearMonth = YearMonth.from(dateInMonth);
        LocalDateTime firstDay = yearMonth.atDay(1).atStartOfDay();
        LocalDateTime lastDay = yearMonth.atEndOfMonth().atTime(23, 59, 59);
        
        // 查询该月的所有交易记录（只计算支出）
        LambdaQueryWrapper<Transaction> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Transaction::getUserId, userId)
                   .eq(Transaction::getIsDeleted, 0)
                   .ge(Transaction::getTransactionDate, firstDay)
                   .le(Transaction::getTransactionDate, lastDay)
                   .exists("SELECT 1 FROM category c WHERE c.id = transaction.category_id AND c.spend = 1");
        
        // 查询交易记录
        List<Transaction> transactions = transactionMapper.selectList(queryWrapper);
        
        // 计算总额
        BigDecimal total = transactions.stream()
                .map(Transaction::getAmount)
                .reduce(BigDecimal.ZERO, BigDecimal::add);
        
        return total;
    }
} 